﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;

namespace Jermaine.UI
{
    /// <summary>
    /// Class to help two way mode data binding
    /// Jermaine
    /// </summary>
    public class DataHandle
    {
        private DataHandle() { }

        public static void SetBinding(Control control, Object dataSource, String propertyName, String fieldName) {
            try {
                control.DataBindings.Add(propertyName, dataSource, fieldName,
                    true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged);
            } catch (ArgumentException) {

            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="control"></param>
        /// <param name="source"></param>
        /// <param name="mappings"></param>
        public static void SetBinding<T>(System.Windows.Forms.Control control, IList<T> source, PropertyMapper mappings) {
            var dataSource = new BindingList<T>(source);

            try {
                foreach (var o in mappings) {
                    var propertyName = o.Key;
                    var fieldName = o.Value;
                    control.DataBindings.Add(propertyName, dataSource, fieldName,
                        true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged);

                }
            } catch (ArgumentException) {

            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="control"></param>
        /// <param name="source"></param>
        /// <param name="mappings"></param>
        public static void SetBinding(System.Windows.Forms.Control control, object source, PropertyMapper mappings) {

            try {
                foreach (var o in mappings) {
                    var propertyName = o.Key;
                    var fieldName = o.Value;
                    control.DataBindings.Add(propertyName, source, fieldName,
                        true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged);

                }
            } catch (ArgumentException) {

            }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public class PropertyMapper : IEnumerable<KeyValuePair<string, string>>
    {
        private Dictionary<string, string> dictionary;

        private PropertyMapper(string file) {
            var root = XElement.Load(file);
            this.dictionary = new Dictionary<string, string>();
            var query = root.Elements("Mapper").Select(o => new { Key = o.Name.LocalName, Value = o.Value });
            foreach (var o in query) {
                dictionary[o.Key] = o.Value;
            }
        }

        private PropertyMapper(Dictionary<string, string> dictionary) {
            this.dictionary = new Dictionary<string, string>(dictionary);
        }

        public PropertyMapper LoadFromXml(string file) {
            return new PropertyMapper(file);
        }
        /// <summary>
        /// Load from dictionary
        /// </summary>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static PropertyMapper LoadFromDictionary(Dictionary<string, string> dictionary) {
            return new PropertyMapper(dictionary);
        }



        public IEnumerator<KeyValuePair<string, string>> GetEnumerator() {
            return dictionary.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return dictionary.GetEnumerator();
        }
    }


    public static class ListExtensions
    {
        public static void BindTo<T>(this IList<T> list, System.Windows.Forms.Control control, PropertyMapper mappings) {
            DataHandle.SetBinding<T>(control, list, mappings);
        }
    }
}
